package net.jgrm.multilevelcache.config;

import org.springframework.boot.context.properties.ConfigurationProperties;

import java.time.Duration;

/**
 * 多级缓存配置属性
 * 支持独立配置Caffeine本地缓存和Redis分布式缓存
 *
 * @author jgrm
 */
@ConfigurationProperties(prefix = "multilevel.cache")
public class MultiLevelCacheProperties {

    /**
     * 是否启用多级缓存
     */
    private boolean enabled = true;

    /**
     * 是否启用线程安全缓存服务
     */
    private boolean threadSafeEnabled = true;

    /**
     * 是否启用分布式缓存同步（适用于集群部署）
     */
    private boolean syncEnabled = false;

    /**
     * 缓存模式：LOCAL_ONLY（仅本地）、REDIS_ONLY（仅Redis）、MULTI_LEVEL（多级）
     */
    private CacheMode mode = CacheMode.MULTI_LEVEL;

    /**
     * Caffeine本地缓存配置
     */
    private Caffeine caffeine = new Caffeine();

    /**
     * Redis缓存配置
     */
    private Redis redis = new Redis();

    // Getters and Setters
    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public boolean isThreadSafeEnabled() {
        return threadSafeEnabled;
    }

    public void setThreadSafeEnabled(boolean threadSafeEnabled) {
        this.threadSafeEnabled = threadSafeEnabled;
    }

    public boolean isSyncEnabled() {
        return syncEnabled;
    }

    public void setSyncEnabled(boolean syncEnabled) {
        this.syncEnabled = syncEnabled;
    }

    public CacheMode getMode() {
        return mode;
    }

    public void setMode(CacheMode mode) {
        this.mode = mode;
    }

    public Caffeine getCaffeine() {
        return caffeine;
    }

    public void setCaffeine(Caffeine caffeine) {
        this.caffeine = caffeine;
    }

    public Redis getRedis() {
        return redis;
    }

    public void setRedis(Redis redis) {
        this.redis = redis;
    }

    /**
     * 缓存模式枚举
     */
    public enum CacheMode {
        /**
         * 仅本地缓存（Caffeine）
         */
        LOCAL_ONLY,
        /**
         * 仅Redis缓存
         */
        REDIS_ONLY,
        /**
         * 多级缓存（Caffeine + Redis）
         */
        MULTI_LEVEL
    }

    /**
     * Caffeine本地缓存配置
     */
    public static class Caffeine {

        /**
         * 是否启用Caffeine缓存
         */
        private boolean enabled = true;

        /**
         * 缓存最大容量
         */
        private long maximumSize = 1000L;

        /**
         * 写入后过期时间
         */
        private Duration expireAfterWrite = Duration.ofMinutes(1);

        /**
         * 访问后过期时间
         */
        private Duration expireAfterAccess;

        /**
         * 刷新间隔时间
         */
        private Duration refreshAfterWrite;

        /**
         * 初始容量
         */
        private int initialCapacity = 16;

        /**
         * 是否记录统计信息
         */
        private boolean recordStats = true;

        /**
         * 是否允许缓存null值
         */
        private boolean allowNullValues = false;

        // Getters and Setters
        public boolean isEnabled() {
            return enabled;
        }

        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }

        public long getMaximumSize() {
            return maximumSize;
        }

        public void setMaximumSize(long maximumSize) {
            this.maximumSize = maximumSize;
        }

        public Duration getExpireAfterWrite() {
            return expireAfterWrite;
        }

        public void setExpireAfterWrite(Duration expireAfterWrite) {
            this.expireAfterWrite = expireAfterWrite;
        }

        public Duration getExpireAfterAccess() {
            return expireAfterAccess;
        }

        public void setExpireAfterAccess(Duration expireAfterAccess) {
            this.expireAfterAccess = expireAfterAccess;
        }

        public Duration getRefreshAfterWrite() {
            return refreshAfterWrite;
        }

        public void setRefreshAfterWrite(Duration refreshAfterWrite) {
            this.refreshAfterWrite = refreshAfterWrite;
        }

        public int getInitialCapacity() {
            return initialCapacity;
        }

        public void setInitialCapacity(int initialCapacity) {
            this.initialCapacity = initialCapacity;
        }

        public boolean isRecordStats() {
            return recordStats;
        }

        public void setRecordStats(boolean recordStats) {
            this.recordStats = recordStats;
        }

        public boolean isAllowNullValues() {
            return allowNullValues;
        }

        public void setAllowNullValues(boolean allowNullValues) {
            this.allowNullValues = allowNullValues;
        }
    }

    /**
     * Redis缓存配置
     */
    public static class Redis {

        /**
         * 是否启用Redis缓存
         */
        private boolean enabled = true;

        /**
         * 默认缓存过期时间
         */
        private Duration defaultTtl = Duration.ofMinutes(5);

        /**
         * 是否缓存null值
         */
        private boolean cacheNullValues = false;

        /**
         * 键前缀
         */
        private String keyPrefix = "cache:";

        /**
         * 是否使用键前缀
         */
        private boolean usePrefix = true;

        /**
         * 序列化类型：JSON, JDK
         */
        private SerializationType serializationType = SerializationType.JSON;

        /**
         * 是否启用类型信息存储（用于JSON序列化）
         */
        private boolean enableDefaultTyping = true;

        // Getters and Setters
        public boolean isEnabled() {
            return enabled;
        }

        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }

        public Duration getDefaultTtl() {
            return defaultTtl;
        }

        public void setDefaultTtl(Duration defaultTtl) {
            this.defaultTtl = defaultTtl;
        }

        public boolean isCacheNullValues() {
            return cacheNullValues;
        }

        public void setCacheNullValues(boolean cacheNullValues) {
            this.cacheNullValues = cacheNullValues;
        }

        public String getKeyPrefix() {
            return keyPrefix;
        }

        public void setKeyPrefix(String keyPrefix) {
            this.keyPrefix = keyPrefix;
        }

        public boolean isUsePrefix() {
            return usePrefix;
        }

        public void setUsePrefix(boolean usePrefix) {
            this.usePrefix = usePrefix;
        }

        public SerializationType getSerializationType() {
            return serializationType;
        }

        public void setSerializationType(SerializationType serializationType) {
            this.serializationType = serializationType;
        }

        public boolean isEnableDefaultTyping() {
            return enableDefaultTyping;
        }

        public void setEnableDefaultTyping(boolean enableDefaultTyping) {
            this.enableDefaultTyping = enableDefaultTyping;
        }

        /**
         * 序列化类型枚举
         */
        public enum SerializationType {
            /**
             * JSON序列化
             */
            JSON,
            /**
             * JDK序列化
             */
            JDK
        }
    }
}